package com.zxcz.service.impl;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.zxcz.domain.Firmware;
import com.zxcz.domain.PageResult;
import com.zxcz.domain.Result;
import com.zxcz.domain.User;
import com.zxcz.mapper.FirmwareMapper;
import com.zxcz.redis.RedisManager;
import com.zxcz.service.FirmwareService;
import com.zxcz.tools.Constants;
import com.zxcz.tools.CustomHttpStatus;
import com.zxcz.tools.RedisKeyBuilder;
import com.zxcz.tools.ResultUtil;

/**
 * 固件包service
 */
@Service
@Transactional
public class FirmwareServiceImpl implements FirmwareService{
	@Autowired
	private FirmwareMapper firmwareMapper;
	@Autowired
	private RedissonClient redisson;
	@Autowired 
	private RedisManager redisManager;
	private static final Log logger = LogFactory.getLog(FirmwareServiceImpl.class);

	/**
	 * 分页
	 */
	@Override
	public PageResult<Firmware> findPage(int pageNum, int pageSize, String userName) {
		
		// 起始位置
		int pageNumber = (pageNum-1) * pageSize;
		List<Firmware> firmwareList = firmwareMapper.queryFirmwareCondition(pageNumber, pageSize, userName);
		Long total = firmwareMapper.getTotal(userName);
		PageResult<Firmware> pageResult = new PageResult<Firmware>();
		pageResult.setRows(firmwareList);
		pageResult.setTotal(total);
		
		return pageResult;
	}

	/**
	 * 添加固件包
	 * @param firmware 需要添加的固件包
	 */
	@Override
	public Result<Object> insertFirmwareIfNotPath(User user, MultipartFile firmwareFile, String version, String host) {
		RLock rLock = redisson.getLock("firmwareLock");
		
		int insertFirmware = 0;
		try {
			// 尝试加锁，最多等待10秒，上锁以后5秒自动解锁
			boolean res = rLock.tryLock(10, 5, TimeUnit.SECONDS);
			if(res) {
				//当前工程路径
				String path = System.getProperty("user.dir");
				//自定义存放文件的文件夹   /storage/用户名/
				String customFolder = File.separator + Constants.FOLDER + File.separator + user.getAccount() + File.separator;
				//获取文件名
				String filename = firmwareFile.getOriginalFilename();
				
				//文件路径
				String filePath = path + customFolder + filename;
				String fileUrl = "http://" + host + customFolder + filename;
				fileUrl = fileUrl.replaceAll("\\\\", "/");
				
				//计算文件MD5值
				InputStream inputStream = firmwareFile.getInputStream();
				String md5Hex = DigestUtils.md5Hex(inputStream);
				inputStream.close();
				//保存到数据库
				Firmware firmware = new Firmware();
				firmware.setPath(filePath);
				firmware.setUrl(fileUrl);
				firmware.setVersion(version);
				firmware.setMd5(md5Hex);
				firmware.setCreatedAt(new Date());
				firmware.setUpdatedAt(new Date());
				firmware.setUserId(user.getId());
				firmware.setUser(user);
				insertFirmware = firmwareMapper.insertFirmwareIfNotPath(firmware);
				
				if(insertFirmware == 0) {
					logger.warn("固件已经存在");
					return ResultUtil.generate(CustomHttpStatus.FILE_EXISTS);
				}
				
				//文件夹不存在则创建
		        File dir = new File(path + customFolder);
		        if(!dir.exists()) {
		        	dir.mkdirs();
				}
				//将文件保存在服务器
				File newFile = new File(filePath);
				firmwareFile.transferTo(newFile);
				
			}
		} catch (Exception e) {
			e.printStackTrace();
			return ResultUtil.generate(CustomHttpStatus.SERVER_ERROR);
		} finally {
			rLock.unlock();
		}
		
		return ResultUtil.generate(CustomHttpStatus.SUCCESS);
		
	}
	
	/**
	 * 更新固件包
	 */
	@Override
	public Result<Object> updateFirmware(Firmware firmware, MultipartFile firmwareFile, String account, String host){
		RLock rLock = redisson.getLock("firmwareLock");
		
		int updateFirmware = 0;
		try {
			boolean res = rLock.tryLock(10, 5, TimeUnit.SECONDS);
			if(res) {
				//当前工程路径
				String path = System.getProperty("user.dir");
				//自定义存放文件的文件夹   /storage/用户名/
				String customFolder = File.separator + Constants.FOLDER + File.separator + account + File.separator;
				//获取文件名
				String filename = firmwareFile.getOriginalFilename();
				
				//文件路径
				String filePath = path + customFolder + filename;
				String fileUrl = "http://" + host + customFolder + filename;
				fileUrl = fileUrl.replaceAll("\\\\", "/");

				//计算文件MD5值
				InputStream inputStream = firmwareFile.getInputStream();
				String md5Hex = DigestUtils.md5Hex(inputStream);
				inputStream.close();
				
				String oldpath = firmwareMapper.getFirmwarePathById(firmware.getId());
				
				//更新到数据库
				firmware.setPath(filePath);
				firmware.setUrl(fileUrl);
				firmware.setMd5(md5Hex);
				firmware.setUpdatedAt(new Date());
				updateFirmware = firmwareMapper.updateFirmwareIfNotPath(firmware);
				
				if(updateFirmware == 0) {
					logger.warn("固件已经存在");
					return ResultUtil.generate(CustomHttpStatus.FILE_EXISTS);
				}
				
				//删除服务器上的旧文件
				File oldFile = new File(oldpath);
				if(oldFile.exists()) {
					oldFile.delete();
				}
				//添加新文件到服务器
				File newFile = new File(filePath);
				firmwareFile.transferTo(newFile);
				
			}
		} catch (Exception e) {
			e.printStackTrace();
			return ResultUtil.generate(CustomHttpStatus.SERVER_ERROR);
		} finally {
			rLock.unlock();
		}
		
		return ResultUtil.generate(CustomHttpStatus.SUCCESS);
	}


	/**
	 * 根据固件包id删除固件包
	 * @param id 固件包id
	 */
	@Override
	public Result<Object> deleteFirmwareById(int id) {
		RLock rLock = redisson.getLock("firmwareLock");
		
		try {
			boolean res = rLock.tryLock(10, 5, TimeUnit.SECONDS);
			if(res) {
				//删除之前先查询出固件包信息
				Firmware firmware = fingFirmwareById(id);
				
				//删除数据库上的固件包
				firmwareMapper.deleteFirmwareById(id);
				
				//删除服务器上的文件
				String path = firmware.getPath();
				File oldFile = new File(path);
				if(oldFile.exists()) {
					oldFile.delete();
				}
				
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
			return ResultUtil.generate(CustomHttpStatus.SERVER_ERROR);
		} finally {
			rLock.unlock();
		}
		
		return ResultUtil.generate(CustomHttpStatus.SUCCESS);
	}
	
	/**
	 * 根据固件包id获取指定固件包
	 * @param id 固件包id
	 */
	private Firmware fingFirmwareById(int id) {
		return firmwareMapper.fingFirmwareById(id);
	}


}
